#ifndef __M_BUFF_H__
#define __M_BUFF_H__

#include "util.hpp"
#include <vector>
#include <cassert>

namespace wmhLog
{
    #define DEFAULT_BUFFER_SIZE (1*1024*1024)
    #define THRESHOLD_BUFFER_SIZE (8*1024*1024)//阈值
    #define INCREAMENT_BUFFER_SIZE (1*1024*1024)//线性增长
    class Buffer
    {
    public:
        Buffer()
            :_buffer(DEFAULT_BUFFER_SIZE),_reader_idx(0),_writer_idx(0)
        {}
        //向缓冲区写入数据
        void push(const char*data,size_t len)
        {
            //缓冲区剩余空间不够：扩容or返回
            //1.返回
            // if(len>writeAbleSize()) return;
            //2.动态扩容
            DynamicIncrease(len);
            //将数据拷贝进缓冲区
            std::copy(data,data+len,&_buffer[_writer_idx]);
            //更新写入位置
            moveWriter(len);
        }

        //返回可写数据长度
        size_t writeAbleSize()
        {
            //对扩容来说，总是可写，此接口仅对于固定大小
            return (_buffer.size()-_writer_idx);
        }
        //返回可读位置起始地址
        const char* begin()
        {
            return &_buffer[_reader_idx];
        }

        //返回可读数据长度
        size_t readerAbleSize()
        {
            //同一个缓冲区空间不会循环使用
            return (_writer_idx-_reader_idx);
        }

        //偏移可读指针
        void movereader(size_t len)
        {
            assert(len<=readerAbleSize());
            _reader_idx+=len;
        }
        //重置读写位置，初始化缓冲区
        void reset()
        {
            _writer_idx=0;
            _reader_idx=0;
        }
        //交换缓冲区
        void swap(Buffer& buffer)
        {
            _buffer.swap(buffer._buffer);//一个类的成员函数可以直接访问同类的其他对象的私有成员 
            std::swap(_reader_idx,buffer._reader_idx);
            std::swap(_writer_idx,buffer._writer_idx);
            
        }
        //判空
        bool empty()
        {
            return _reader_idx==_writer_idx;
        }
    private:
        //扩容
        void DynamicIncrease(size_t len)
        {
            if(len<=writeAbleSize()) return;
            size_t new_size=0;
            if(_buffer.size()<THRESHOLD_BUFFER_SIZE)//超过阈值翻倍
            {
                new_size=_buffer.size()*2+len;
            }
            else
            {
                //线性增长
                new_size=_buffer.size()+INCREAMENT_BUFFER_SIZE+len;
            }
            _buffer.resize(new_size);
        }
        //写指针偏移
        void moveWriter(size_t len)
        {
            assert((len+_writer_idx)<=_buffer.size());
            _writer_idx+=len;
        }
    private:
        std::vector<char> _buffer;//缓冲区
        size_t _reader_idx;//可读位置下标    
        size_t _writer_idx;//可写位置下标   
    };

}



#endif